package cz.muni.fi.pa165.restclient;

import cz.muni.fi.pa165.api.dto.PickerDTO;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.util.ResourceBundle;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

/**
 * PickerHandler class represents a picker part of menu
 *
 * @author Michal Becak
 */
public class PickerHandler {

    private BufferedReader reader;
    private RestTemplate rt = new RestTemplate();
    private ResourceBundle rb = ResourceBundle.getBundle("cz.muni.fi.pa165.restclient.resources.urlPaths");

    public PickerHandler(BufferedReader reader) {
        this.reader = reader;
    }

    public void pickerMenu() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Picker menu");
            System.out.println("1. Create picker");
            System.out.println("2. Update picker");
            System.out.println("3. Delete picker");
            System.out.println("4. Get all pickers");
            System.out.println("5. Get picker by nickname");
            System.out.println("6. Get picker by first name");
            System.out.println("7. Get picker by last name");
            System.out.println("Make your selection {1, 2, 3, 4, 5, 6, 7}, m for main menu, x for exit");
            String result = reader.readLine();
            switch (result) {
                case "1":
                    createPicker();
                    break;
                case "2":
                    updatePicker();
                    break;
                case "3":
                    deletePicker();
                    break;
                case "4":
                    getAllPickers();
                    break;
                case "5":
                    getPickerByNickName();
                    break;
                case "6":
                    getPickerByFirstName();
                    break;
                case "7":
                    getPickerByLastName();
                    break;
                case "m":
                    return;
                case "x":
                    System.exit(0);
                default:
                    System.out.println("Invalid choice, try again!");
            }
        }
    }

    public void createPicker() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Create a new picker");
            System.out.println("Enter the nickname: (required)");
            String nickName = reader.readLine();
            if (nickName.isEmpty()) {
                System.out.println("Fill the nickname.");
                continue;
            }
            try {
                PickerDTO pickerCheck = rt.getForObject(rb.getString("serverPath") + rb.getString("getPickerByNickName"),
                        PickerDTO.class, nickName);
                if (pickerCheck != null) {
                    System.out.println("Picker with given nickname already exists.");
                    continue;
                }
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            System.out.println("Enter the password: (required)");
            String password = reader.readLine();
            if (password.isEmpty()) {
                System.out.println("Fill the password.");
                continue;
            }
            
            System.out.println("Enter the first name: (required)");
            String firstName = reader.readLine();
            if (firstName.isEmpty()) {
                System.out.println("Fill the first name.");
                continue;
            }
            System.out.println("Enter the last name: (required)");
            String lastName = reader.readLine();
            if (lastName.isEmpty()) {
                System.out.println("Fill the last name.");
                continue;
            }
            System.out.println("Enter some personal info: (optional)");
            String info = reader.readLine();

            PickerDTO pickerDTO = new PickerDTO();
            pickerDTO.setNickName(nickName);
            pickerDTO.setPassword(password);
            pickerDTO.setFirstName(firstName);
            pickerDTO.setLastName(lastName);
            pickerDTO.setPickerInfo(info);
            pickerDTO.setUserRole(PickerDTO.UserRole.ROLE_USER);
            try {
                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("createPicker"), pickerDTO);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    public void updatePicker() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Update picker");
            PickerDTO picker = null;
            try {
                PickerDTO[] pickers = rt.getForObject(rb.getString("serverPath") + rb.getString("getAllPickers"), PickerDTO[].class);
                printPickers(pickers);
                boolean isIDSuccessful = false;
                Long id;
                while (!isIDSuccessful) {
                    try {
                        System.out.println("Choose picker's id number");
                        id = Long.valueOf(reader.readLine());
                    } catch (NumberFormatException ex) {
                        System.out.println("ID must be correctly filled number.");
                        continue;
                    }
                    picker = getPicker(id);
                    if (picker == null) {
                        System.out.println("Picker with given ID does not exist.");
                    } else {
                        isIDSuccessful = true;
                    }
                }
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            String nickname = null;
            String firstName = null;
            String lastName = null;
            String pickerInfo = null;

            do {
                System.out.println("Enter new nickname (old nickname: "
                        + picker.getNickName() + ") (required)");
                nickname = reader.readLine();
                if (nickname.isEmpty()) {
                    System.out.println("Nickname is required to be filled, try again.");
                    continue;
                }
                try {
                    PickerDTO pickerCheck = rt.getForObject(rb.getString("serverPath") + rb.getString("getPickerByNickName"),
                            PickerDTO.class, nickname);
                    if (pickerCheck != null) {
                        System.out.println("This nickname already exists.");
                        continue;
                    }
                } catch (HttpServerErrorException ex) {
                    System.out.println("Error has occured, returning back to menu.");
                    return;
                }
            } while (nickname.isEmpty());


            do {
                System.out.println("Enter new first name(old first name: "
                        + picker.getFirstName() + ") (required)");
            } while ((firstName = reader.readLine()).isEmpty());


            do {
                System.out.println("Enter new last name (old last name: "
                        + picker.getLastName() + ") (required)");
            } while ((lastName = reader.readLine()).isEmpty());

            System.out.println("Enter new personal info (old personal info: "
                    + picker.getPickerInfo() + ") (optional)");
            pickerInfo = reader.readLine();

            picker.setNickName(nickname);
            picker.setFirstName(firstName);
            picker.setLastName(lastName);
            picker.setPickerInfo(pickerInfo);

            try {
                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("updatePicker"), picker);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    public void deletePicker() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Delete picker");
            PickerDTO picker = null;
            try {
                PickerDTO[] pickers = rt.getForObject(rb.getString("serverPath") + rb.getString("getAllPickers"), PickerDTO[].class);
                printPickers(pickers);
                boolean isIDSuccessful = false;
                Long id;
                while (!isIDSuccessful) {
                    try {
                        System.out.println("Choose picker's id number");
                        id = Long.valueOf(reader.readLine());
                    } catch (NumberFormatException ex) {
                        System.out.println("ID must be correctly filled number.");
                        continue;
                    }
                    picker = getPicker(id);
                    if (picker == null) {
                        System.out.println("Picker with given ID does not exist.");
                    } else {
                        isIDSuccessful = true;
                    }
                }
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            System.out.println("Are you sure? All forest visits with given picker will be removed! (y/n)");
            String res = reader.readLine();
            switch (res) {
                case "y":
                    break;
                case "n":
                    return;
                default:
                    System.out.println("Incorrect choice, returning back to picker menu");
                    return;
            }
            try {
                URI uri = rt.postForLocation(rb.getString("serverPath") + rb.getString("removePicker"), picker);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    public void getAllPickers() throws IOException {
        System.out.println("");
        System.out.println("List of all pickers:");
        try {
            PickerDTO[] pickers = rt.getForObject(rb.getString("serverPath") + rb.getString("getAllPickers"), PickerDTO[].class);
            printPickers(pickers);
        } catch (HttpServerErrorException ex) {
            System.out.println("Error has occured, returning back to menu.");
            return;
        }
        System.out.println("Choose your action: r - return to picker menu, x - exit");
        for (;;) {
            String result = reader.readLine();
            switch (result) {
                case "r":
                    return;
                case "x":
                    System.exit(0);
                default:
                    System.out.println("Incorrect choice, try again!");
                    System.out.println("Choose your action: r - return to picker menu, x - exit");
            }
        }
    }

    public void getPickerByNickName() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Enter picker's nickname:");
            String name = reader.readLine();
            if (name.isEmpty()) {
                continue;
            }
            PickerDTO pickerDTO;
            try {
                pickerDTO = rt.getForObject(rb.getString("serverPath") + rb.getString("getPickerByNickName"), PickerDTO.class, name);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (pickerDTO == null) {
                System.out.append("Picker with given nickname does not exist.");
            } else {
                System.out.printf("Id: %d, nickname: %s, first name: %s, last name: %s, info: %s%n",
                        pickerDTO.getId(), pickerDTO.getNickName(), pickerDTO.getFirstName(),
                        pickerDTO.getLastName(), pickerDTO.getPickerInfo());
            }
            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    public void getPickerByFirstName() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Enter picker's first name:");
            String name = reader.readLine();
            if (name.isEmpty()) {
                continue;
            }
            PickerDTO[] pickers;
            try {
                pickers = rt.getForObject(rb.getString("serverPath") + rb.getString("getPickerByFirstName"), PickerDTO[].class, name);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (pickers.length == 0) {
                System.out.println("No picker with given name exists.");
            } else {
                System.out.println("Returned pickers:");
                printPickers(pickers);
            }

            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    public void getPickerByLastName() throws IOException {
        for (;;) {
            System.out.println("");
            System.out.println("Enter picker's last name:");
            String name = reader.readLine();
            if (name.isEmpty()) {
                continue;
            }
            PickerDTO[] pickers;
            try {
                pickers = rt.getForObject(rb.getString("serverPath") + rb.getString("getPickerByLastName"), PickerDTO[].class, name);
            } catch (HttpServerErrorException ex) {
                System.out.println("Error has occured, returning back to menu.");
                return;
            }
            if (pickers.length == 0) {
                System.out.println("No picker with given name exists.");
            } else {
                System.out.println("Returned pickers:");
                printPickers(pickers);
            }

            if (!repeatSameStepDialog()) {
                return;
            }
        }
    }

    private void printPickers(PickerDTO[] p) {
        for (PickerDTO pickerDTO : p) {
            System.out.printf("Id: %d, nickname: %s, first name: %s, last name: %s, info: %s%n",
                    pickerDTO.getId(), pickerDTO.getNickName(), pickerDTO.getFirstName(),
                    pickerDTO.getLastName(), pickerDTO.getPickerInfo());
        }
    }

    private PickerDTO getPicker(Long id) {
        return rt.getForObject(rb.getString("serverPath") + rb.getString("getPicker"), PickerDTO.class, id.toString());
    }

    private boolean repeatSameStepDialog() throws IOException {
        System.out.println("Choose your action: c - continue, r - return to picker menu, x - exit");
        boolean cont = true;
        while (cont) {
            String result = reader.readLine();
            switch (result) {
                case "c":
                    cont = false;
                    break;
                case "r":
                    return false;
                case "x":
                    System.exit(0);
                default:
                    System.out.println("Incorrect choice, try again!");
                    System.out.println("Choose your action: c - continue, r - return to picker menu, x - exit");
            }
        }
        return true;
    }
}
